import { gkhCreate, RecordOperation } from './tools';
import { wordCells } from './TableCellType';
import { createRightMenu } from './RightMenu';
/**
 * 动态表单
 * @param {*} node 存放表单的父级容器
 * @param {*} mode @default 3 模式：1：绘制模式、2：编辑模式、3：查看模式 
 * @returns 
 */
const GkhTableTemplate = function (node, mode, parentComponent) {
  const me = this;
  this.name = 'gukhTableTemplate';
  this.type = 1; // 1:table  2:word
  const container = gkhCreate('div', { target: node, className: 'gkh_table_template' });
  const tableContainer = gkhCreate('table', { target: container, attribute: { border: '1' } });
  const tbody = gkhCreate('tbody', { target: tableContainer });
  // 表格单元格类名
  const tdClassName = 'gkh_td'.concat(Math.floor(Math.random() * 100000000).toString());
  // 表格单元格数组
  let tableCells = [];
  // 表格单元格位置大小数组
  let cellInfos = [];
  // 选中的单元格
  let selectedCell = [];
  let selectedCellBack = [];
  // 已选取的元素背景颜色
  const selectedTdBColor = '#e5f8fd';
  // 单元格最小尺寸
  const cellMinSize = 12;
  // 表格操作记录
  const handleRecord = new RecordOperation(20);

  // 鼠标是否按下
  let mouseHasDown = false;
  // 是否是调整单元格大小
  let adjustSize = false;
  // 是否允许改变单元格尺寸
  const allowChangeSize = true;
  // 鼠标按下所在的单元格td
  let mouseDownCell;
  // 鼠标按下时的位置
  let downPoint;
  // 鼠标按下时单元格信息
  let downCellInfo;
  // 单元格是否发生变化
  let cellHasChange = false;
  // 合并的行
  let mergeRowSpan = 0;
  // 合并的列
  let mergeColSpan = 0;
  // 当前列的行数统计数组
  let rowSpanCount = [];
  // 当前行的列数统计数组
  let colSpanCount = [];
  // 表格行数
  let tableRows = 0;
  // 表格列数
  let tableCols = 0;
  let tableWidth = 100;
  // 合并单元格的单元
  let mergeCellInfo;
  // 合并单元格对角单元
  let mergeDiagonalCellInfo;
  // 合并按钮是否禁用
  let mergeButDisabled = true;

  // 新增按钮数组
  let addButtons = [];
  // 管理整个表格输入字段值操作 设置值setValue 获取值getValue  
  let valueHandle = {};
  let groupComponents = {};


  // 单元格位置或大小发生变化调用此函数 跟新相应数据
  function cellChange(hasClear) {
    const { childNodes: trs } = tbody;
    const removeTrs = [];
    const adjustTrs = [];
    let tr;
    let tds;
    let td;
    let obj;
    let tdinfos = [];
    cellInfos = [];
    tableCells = [];
    colSpanCount = [];
    rowSpanCount = [];
    const { screenX, screenY } = window;
    let indexI = 0;
    let indexJ = 0;
    let temp = 0;
    let notExistOne = true;
    let minRowSpan = 100000;
    let k = 0;
    let m = 0;
    for (let i = 0; i < trs.length; i += 1) {
      tds = trs[i].childNodes;
      notExistOne = true;
      if (tds.length < 1) {
        tbody.removeChild(trs[i]);
        k = i - 1;
        while (k >= 0) {
          tds = trs[k].childNodes;
          if (tds.length > 0) {
            m = i - k + 1;
            for (let j = 0; j < tds.length; j += 1) {
              if (tds[j].rowSpan >= m) {
                tds[j].rowSpan -= 1;
              }
            }
          }
          k -= 1;
        }
      } else {
        minRowSpan = 100000;
        for (let j = 0; j < tds.length; j += 1) {
          const { rowSpan, colSpan } = tds[j];
          if (rowSpan === 1) {
            notExistOne = false;
          }
          if (minRowSpan > rowSpan) {
            minRowSpan = rowSpan;
          }
        }
        // if (notExistOne) {
        //   minRowSpan -= 1;
        //   for (let j = 0; j < tds.length; j += 1) {
        //     tds[j].rowSpan -= minRowSpan;
        //   }
        // }
      }
    }
    for (let i = 0; i < trs.length; i += 1) {
      tr = trs[i];
      tds = tr.childNodes;
      tdinfos = cellInfos[indexI] ? cellInfos[indexI] : [];
      indexJ = 0;
      colSpanCount.push(tds.length);
      for (let j = 0; j < tds.length; j += 1) {
        td = tds[j];
        const {
          bottom,
          top,
          left,
          right,
          height,
          width: cellWidth,
          x,
          y,
        } = td.getBoundingClientRect();
        const { rowSpan, colSpan } = td;
        obj = {
          node: td,
          bottom: screenY + bottom,
          top: screenY + top,
          left: screenX + left,
          right: screenX + right,
          height,
          width: cellWidth,
          x,
          y,
          rowSpan,
          colSpan,
        };
        while (tdinfos[indexJ] === false) {
          indexJ += 1;
        }
        tdinfos[indexJ] = obj;
        td.positionX = indexI;
        td.positionY = indexJ;
        let k = colSpan;
        while (k > 1) {
          k -= 1;
          tdinfos[indexJ + k] = false;
        }
        let m = rowSpan;
        while (m > 1) {
          k = colSpan;
          m -= 1;
          const infos = cellInfos[indexI + m] ? cellInfos[indexI + m] : [];
          while (k > 0) {
            k -= 1;
            infos[indexJ + k] = false;
          }
          cellInfos[indexI + m] = infos;
        }
        indexJ += colSpan;
      }
      cellInfos[indexI] = tdinfos;
      tableCells.push(tds);
      indexI += 1;
    }

    if (removeTrs.length > 0) {
      removeTrs.forEach((trCell) => {
        tbody.removeChild(trCell);
      });
    }
    tableCols = indexJ;
    tableRows = indexI;
    for (let i = 0; i < indexJ; i += 1) {
      temp = 0;
      for (let j = 0; j < indexI; j += 1) {
        if (cellInfos[j][i]) {
          temp += 1;
        }
      }
      rowSpanCount.push(temp);
    }
    if (hasClear !== false) {
      if (mouseDownCell) {
        mouseDownCell.style.boxShadow = 'none';
        mouseDownCell = null;
      }
      clearSelected();
    }
  }

  function renderAfter() {
    let infos;
    let info;
    for (let i = 0; i < cellInfos.length; i += 1) {
      infos = cellInfos[i];
      for (let j = 0; j < infos.length; j += 1) {
        info = infos[j];
        if (info && info.node.cellType.renderAfter) {
          info.node.cellType.renderAfter();
        }
      }
    }
  }

  function createTd(attrData={}, style, rowSpan, colSpan, groupIndex, value) {
    const cellType = wordCells.getComponent(me, mode, attrData);
    if (attrData.groupName) {
      if (groupComponents[attrData.groupName]) {
        if (!groupIndex) {
          groupIndex = 0;
        }
        groupComponents[attrData.groupName][groupIndex].push(cellType);
      } else {
        groupComponents[attrData.groupName] = [[cellType]];
      }
      if (value && attrData.fieldName && cellType.setValue) {
        cellType.setValue(value[attrData.fieldName]);
      }
    } else if (attrData.fieldName && cellType.getValue && cellType.setValue) {
      valueHandle[attrData.fieldName] = {
        getValue: cellType.getValue,
        setValue: cellType.setValue
      }
    }
    const td = gkhCreate('td', {
      style,
      child: cellType.render(),
      className: tdClassName,
    });
    td.cellType = cellType;
    if (rowSpan) {
      td.rowSpan = rowSpan;
    }
    if (colSpan) {
      td.colSpan = colSpan;
    }
    if (mode == 1) {
      changeTdType(td);
    } else if (attrData.type == 5) {
      addButtons.push(cellType);
    }
    return td;
  }

  this.init = (row = 10, col = 10) => {
    tbody.innerHTML = '';
    let tr;
    let td;
    let cellType;
    const width = tbody.offsetWidth / col;
    for (let i = 0; i < row; i += 1) {
      tr = gkhCreate('tr', { target: tbody });
      for (let j = 0; j < col; j += 1) {
        cellType = wordCells.getComponent(me, mode);
        td = gkhCreate('td', {
          target: tr,
          child: cellType.render(),
          className: tdClassName,
          style: {
            width: width.toString().concat('px')
          }
        });
        td.cellType = cellType;
        td.positionX = i;
        td.positionY = j;
        if (mode == 1) {
          changeTdType(td);
        }
      }
    }
    cellChange();
    renderAfter();
    pushHandle();
  };

  if(node){
    node.addEventListener('scroll',()=>cellChange())
  }

  function changeTdType(td) {
    td.ondragover = function (event) {
      event.preventDefault();
      event.stopPropagation();
      event.cancelBubble = true;
      return false;
    }
    td.ondrop = function (event) {
      event.preventDefault();
      var data = event.dataTransfer.getData("gkhWordCellId");
      event.dataTransfer.setData("gkhWordCellId", undefined);
      if (data) {
        td.cellType = wordCells.getComponent(me, mode, { type: parseInt(data) });
        td.innerHTML = "";
        td.appendChild(td.cellType.render());
        if (td.cellType.renderAfter) {
          td.cellType.renderAfter();
        }
        cellChange();
      }
      event.stopPropagation();
      event.cancelBubble = true;
      return false;
    }
  }

  function findTd(node) {
    let n = node;
    for (let i = 0; i < 10; i += 1) {
      if (n.className && n.className.indexOf(tdClassName) > -1) {
        return n;
      }
      n = n.parentNode;
    }
    return null;
  }
  function clearSelected() {
    if (selectedCell && selectedCell.length > 0) {
      selectedCell.forEach(({ node }) => {
        node.style.backgroundColor = node.bgColor;
      });
    }
    selectedCellBack = selectedCell;
    selectedCell = [];
  }

  // 提取表单单元格数据
  function getCellData(info) {
    const { node, rowSpan, colSpan, width, height } = info;
    const {
      fontSize,
      color,
      fontWeight,
      lineHeight,
      backgroundColor,
      textAlign,
      verticalAlign
    } = window.getComputedStyle(node);
    return [
      rowSpan,
      colSpan,
      Number((width / tableWidth).toFixed(4)),
      height,
      node.cellType.getAttrData(),
      [fontSize, color, fontWeight, lineHeight, backgroundColor, textAlign, verticalAlign],
    ];
  }

  // 获取表单模板数据
  function tableTemplateData() {
    tableWidth = tbody.offsetWidth;
    const cellDatas = [];
    for (let i = 0; i < cellInfos.length; i += 1) {
      const arr = [];
      cellInfos[i].forEach(info => {
        if (info) {
          arr.push(getCellData(info));
        }
      })
      cellDatas.push(arr);
    }
    return {
      cellDatas,
      border: tableContainer.border,
      borderColor: tableContainer.style.borderColor
    };
  }

  function setCellStyle(item) {
    return {
      width: (tableWidth * item[2]).toString().concat('px'),
      height: item[3].toString().concat('px'),
      fontSize: item[5][0],
      color: item[5][1],
      fontWeight: item[5][2],
      lineHeight: item[5][3],
      backgroundColor: item[5][4],
      textAlign: item[5][5],
      verticalAlign: item[5][6],
    };
  }

  // 已有表单数据渲染表单
  function renderTableTemplate(templateData) {
    tbody.innerHTML = '';
    valueHandle = {};
    groupComponents = {};
    if (templateData instanceof Object && templateData.cellDatas instanceof Array) {
      tableContainer.setAttribute('border', templateData.border);
      tableContainer.style.borderColor = templateData.borderColor;
      tableWidth = tbody.offsetWidth;
      let cells;
      let tr;
      let item;
      let trs = [];
      for (let i = 0; i < templateData.cellDatas.length; i += 1) {
        cells = templateData.cellDatas[i];
        if (cells instanceof Array) {
          tr = gkhCreate('tr');
          for (let j = 0; j < cells.length; j += 1) {
            item = cells[j];
            tr.appendChild(createTd(item[4], setCellStyle(item), item[0], item[1]));
          }
          trs.push(tr);
        } else {
          tbody.innerHTML = '';
          console.warn('传入数据格式不对！', cells);
          break;
        }
      }
      trs.forEach((item) => tbody.appendChild(item));
      cellChange();
      renderAfter();
    } else {
      console.warn('传入数据格式不对！', templateData);
    }
  }


  // 记录操作
  function pushHandle() {
    const templateData = tableTemplateData();
    handleRecord.push(templateData);
  }

  // 测回回退记录
  function nextHandle() {
    renderTableTemplate(handleRecord.next());
  }

  // 回退记录
  function backHandle() {
    renderTableTemplate(handleRecord.back());
  }

  // 右键菜单
  let rightMenu;
  if (mode == 1) {
    rightMenu = createRightMenu(container);
    rightMenu.addItem([
      {
        id: 'mergeBut',
        text: '合并单元格',
        click: mergeCell,
      },
    ]);
    rightMenu.addItem([
      {
        id: 'splitCellByRow',
        text: '按行拆分',
        click: splitCellByRow,
      },
      {
        id: 'splitCellByCol',
        text: '按列拆分',
        click: splitCellByCol,
      },
    ]);
    rightMenu.addItem([
      {
        id: 'insertAfterRow',
        text: '往后新增行',
        click: insertAfterRow,
      },
      {
        id: 'insertBeforeRow',
        text: '往前新增行',
        click: insertBeforeRow,
      },
    ]);
    rightMenu.addItem([
      {
        id: 'addColAfter',
        text: '往后新增列',
        click: addColAfter,
      },
      {
        id: 'addColBefore',
        text: '往前新增列',
        click: addColBefore,
      },
    ]);
    rightMenu.addItem([
      {
        id: 'delRow',
        text: '删除行',
        click: delRow,
      },
      {
        id: 'delCol',
        text: '删除列',
        click: delCol,
      },
    ]);
    rightMenu.addItem([
      {
        id: 'backHandle',
        text: '回退',
        click: backHandle,
      },
      {
        id: 'nextHandle',
        text: '撤销',
        click: nextHandle,
      },
    ]);
  }

  function onRightDown() {
    if (selectedCell.length < 2) {
      mergeButDisabled = true;
    }
    const butDisabled = !(selectedCell.length < 2 && mouseDownCell);
    let splitRowDisabled = butDisabled;
    let splitColDisabled = butDisabled;
    if (!butDisabled) {
      const { rowSpan, colSpan, offsetWidth, offsetHeight } = mouseDownCell;
      splitRowDisabled = offsetHeight < cellMinSize || !(rowSpan === 1 || rowSpan % 2 === 0);
      splitColDisabled = offsetWidth < cellMinSize || !(colSpan === 1 || colSpan % 2 === 0);
    }

    rightMenu.items.mergeBut.disabled = mergeButDisabled;
    rightMenu.items.splitCellByRow.disabled = splitRowDisabled;
    rightMenu.items.splitCellByCol.disabled = splitColDisabled;
    rightMenu.items.insertAfterRow.disabled = butDisabled;
    rightMenu.items.insertBeforeRow.disabled = butDisabled;
    rightMenu.items.addColAfter.disabled = butDisabled;
    rightMenu.items.addColBefore.disabled = butDisabled;
    rightMenu.items.delRow.disabled = butDisabled;
    rightMenu.items.delCol.disabled = butDisabled;
    rightMenu.items.backHandle.disabled = !handleRecord.hasBack;
    rightMenu.items.nextHandle.disabled = !handleRecord.hasNext;
  }

  function clearSelectedCell() {
    if (mouseDownCell) {
      mouseDownCell.style.boxShadow = 'none';
      mouseDownCell = undefined;
    }
  }

  // 鼠标按下记录位置
  function onMouseDown(event) {
    const { target, which } = event;
    const { screenX, screenY } = window;
    const clientX = event.clientX + screenX;
    const clientY = event.clientY + screenY;
    if (which === 3) {
      onRightDown();
      return true;
    }
    if (mouseDownCell) {
      mouseDownCell.style.boxShadow = 'none';
    }
    mouseDownCell = findTd(target);
    me.selectedNode = mouseDownCell;
    if (mouseDownCell) {
      if (me.selectedCellChange) {
        me.selectedCellChange(window.getComputedStyle(mouseDownCell), mouseDownCell.cellType, me);
      }
      mouseHasDown = true;
      mouseDownCell.style.boxShadow = '#a4cfef 0px 0px 5px 1px inset';
      downPoint = {
        x: clientX,
        y: clientY,
      };
      const { rowSpan, colSpan, positionX, positionY, offsetWidth, offsetHeight } = mouseDownCell;
      downCellInfo = {
        minWidth: 0,
        nextMinWidth: 0,
        minHeight: 0,
        adjustCellInfos: [],
        adjustRightCellInfos: [],
        hasChange: false,
      };
      const adjustCellInfos = [];
      const adjustRightCellInfos = [];
      // 调整单元格尺寸
      if (adjustSize === 1) {
        const index = positionY + colSpan - 1;
        const nextIndex = index + 1;
        if (tableCols >= nextIndex) {
          let minWidth = 1000000;
          let nextMinWidth = 1000000;
          let info;
          let info2;
          for (let i = 0; i < cellInfos.length; i += 1) {
            info = cellInfos[i][index];
            if (info) {
              adjustCellInfos.push({
                width: info.width,
                node: info.node,
              });
              if (minWidth > info.width) {
                minWidth = info.width;
              }
            }
            info2 = cellInfos[i][nextIndex];
            if (info2) {
              adjustRightCellInfos.push({
                width: info2.width,
                node: info2.node,
              });
              if (nextMinWidth > info2.width) {
                nextMinWidth = info2.width;
              }
            }
          }
          downCellInfo.minWidth = minWidth;
          downCellInfo.nextMinWidth = nextMinWidth;
          downCellInfo.adjustCellInfos = adjustCellInfos;
          downCellInfo.adjustRightCellInfos = adjustRightCellInfos;
          downCellInfo.hasChange = true;
        }
      } else if (adjustSize === 2) {
        const infos = cellInfos[positionX + rowSpan - 1];
        let info;
        let minHeight = 1000000;
        for (let i = 0; i < infos.length; i += 1) {
          info = infos[i];
          if (info) {
            adjustCellInfos.push({
              height: info.height,
              node: info.node,
            });
            i += info.colSpan - 1;
            if (minHeight > info.height) {
              minHeight = info.height;
            }
          } else {
            for (let j = positionX - 1; j >= 0; j -= 1) {
              info = cellInfos[j][i];
              if (info && info.rowSpan > 1) {
                adjustCellInfos.push({
                  height: info.height,
                  node: info.node,
                });
                i += info.colSpan - 1;
                break;
              }
            }
          }
        }
        downCellInfo.minHeight = minHeight;
        downCellInfo.adjustCellInfos = adjustCellInfos;
      }
    }
    clearSelected();
    cellHasChange = false;
    event.stopPropagation();
    event.cancelBubble = true;
    return false;
  }

  // 鼠标移动 选中单元格
  function onMouseMove(event) {
    const { target } = event;
    const { screenX, screenY } = window;
    const clientX = event.clientX + screenX;
    const clientY = event.clientY + screenY;
    if (mouseHasDown) {
      const {
        minHeight,
        adjustCellInfos,
        minWidth,
        nextMinWidth,
        adjustRightCellInfos,
        hasChange,
      } = downCellInfo;
      if (adjustSize) {
        // 调整单元格尺寸
        if (adjustSize === 1) {
          if (downCellInfo.hasChange) {
            const dw = clientX - downPoint.x;
            if (dw + minWidth > 24 && nextMinWidth - dw > 24) {
              cellHasChange = true;
              adjustCellInfos.forEach(({ width, node }) => {
                node.style.width = (width + dw).toString().concat('px');
              });
              adjustRightCellInfos.forEach(({ width, node }) => {
                node.style.width = (width - dw).toString().concat('px');
              });
            }
          }
        } else if (adjustSize === 2) {
          const dh = clientY - downPoint.y;
          if (dh + minHeight > 24) {
            cellHasChange = true;
            adjustCellInfos.forEach(({ height, node }) => {
              node.style.height = (height + dh).toString().concat('px');
            });
          }
        }
      } else if (mouseDownCell) {
        // 选择单元格
        clearSelected();
        let infos;
        let info;
        let indexI = mouseDownCell.positionX;
        let indexJ = mouseDownCell.positionY;
        let hasNext = false;
        let spanCount = 0;
        // 合并的行
        mergeRowSpan = 0;
        // 合并的列
        mergeColSpan = 0;
        mergeButDisabled = false;
        const { left: downLeft, top: downTop, bottom: downBottom, right: downRight } = cellInfos[
          indexI
        ][indexJ];
        if (clientX - downPoint.x > 0) {
          // 向右
          while (true) {
            if (rowSpanCount[indexJ] === tableCols || indexJ === 0) {
              break;
            }
            indexJ -= 1;
          }
          if (clientY - downPoint.y > 0) {
            while (true) {
              if (colSpanCount[indexI] === tableRows || indexI === 0) {
                break;
              }
              indexI -= 1;
            }
            // 向右下
            for (let i = indexI; i < cellInfos.length; i += 1) {
              infos = cellInfos[i];
              for (let j = indexJ; j < infos.length; j += 1) {
                info = infos[j];
                if (info) {
                  const { left, node, right, top, bottom, rowSpan, colSpan } = info;
                  if (clientY < top) {
                    hasNext = true;
                    break;
                  }
                  if (clientX >= left) {
                    if (right > downLeft && bottom > downTop) {
                      node.bgColor = node.style.backgroundColor;
                      node.style.backgroundColor = selectedTdBColor;
                      selectedCell.push(info);
                      if (top === downTop) {
                        mergeColSpan += colSpan;
                      }
                      if (left === downLeft) {
                        mergeRowSpan += rowSpan;
                      }
                      spanCount += rowSpan * colSpan;
                    }
                  } else {
                    break;
                  }
                }
              }
              if (hasNext) {
                break;
              }
            }
            mergeCellInfo = selectedCell[0];
            mergeDiagonalCellInfo = selectedCell[selectedCell.length - 1];
          } else {
            // 向右上
            while (true) {
              if (colSpanCount[indexI] === tableRows || indexI === tableRows - 1) {
                break;
              }
              indexI += 1;
            }
            for (let i = indexI; i >= 0; i -= 1) {
              infos = cellInfos[i];
              for (let j = indexJ; j < infos.length; j += 1) {
                info = infos[j];
                if (info) {
                  const { left, node, right, top, bottom, rowSpan, colSpan } = info;
                  if (clientY > bottom && colSpanCount[i] === tableRows && j === infos.length - 1) {
                    hasNext = true;
                    break;
                  }
                  if (clientX >= left) {
                    if (right > downLeft && top < downBottom && bottom >= clientY) {
                      if (j === mouseDownCell.positionY) {
                        mergeCellInfo = info;
                      }
                      if (i === mouseDownCell.positionX) {
                        mergeDiagonalCellInfo = info;
                      }
                      node.bgColor = node.style.backgroundColor;
                      node.style.backgroundColor = selectedTdBColor;
                      selectedCell.push(info);
                      if (bottom === downBottom) {
                        mergeColSpan += colSpan;
                      }
                      if (left === downLeft) {
                        mergeRowSpan += rowSpan;
                      }
                      spanCount += rowSpan * colSpan;
                    }
                  } else {
                    break;
                  }
                }
              }
              if (hasNext) {
                break;
              }
            }
          }
        } else if (clientY - downPoint.y > 0) {
          // 向左
          while (true) {
            if (rowSpanCount[indexJ] === tableCols || indexJ === tableCols - 1) {
              break;
            }
            indexJ += 1;
          }
          while (true) {
            if (colSpanCount[indexI] === tableRows || indexI === 0) {
              break;
            }
            indexI -= 1;
          }
          // 向左下
          for (let i = indexI; i < cellInfos.length; i += 1) {
            infos = cellInfos[i];
            for (let j = indexJ; j >= 0; j -= 1) {
              info = infos[j];
              if (info) {
                const { left, node, right, top, bottom, rowSpan, colSpan } = info;
                if (clientY < top) {
                  hasNext = true;
                  break;
                }
                if (clientX <= right) {
                  if (left < downRight && bottom > downTop) {
                    if (i === mouseDownCell.positionX) {
                      mergeCellInfo = info;
                    }
                    if (j === mouseDownCell.positionY) {
                      mergeDiagonalCellInfo = info;
                    }
                    node.bgColor = node.style.backgroundColor;
                    node.style.backgroundColor = selectedTdBColor;
                    selectedCell.push(info);
                    if (top === downTop) {
                      mergeColSpan += colSpan;
                    }
                    if (right === downRight) {
                      mergeRowSpan += rowSpan;
                    }
                    spanCount += rowSpan * colSpan;
                  }
                } else {
                  break;
                }
              }
            }
            if (hasNext) {
              break;
            }
          }
        } else {
          while (true) {
            if (rowSpanCount[indexJ] === tableCols || indexJ === tableCols - 1) {
              break;
            }
            indexJ += 1;
          }
          while (true) {
            if (colSpanCount[indexI] === tableRows || indexI === tableRows - 1) {
              break;
            }
            indexI += 1;
          }
          // 向左上
          for (let i = indexI; i >= 0; i -= 1) {
            infos = cellInfos[i];
            for (let j = indexJ; j >= 0; j -= 1) {
              info = infos[j];
              if (info) {
                const { left, node, right, top, bottom, rowSpan, colSpan } = info;
                if (clientY > bottom && colSpanCount[i] === tableRows && j === 0) {
                  hasNext = true;
                  break;
                }
                if (clientX <= right) {
                  if (left < downRight && top < downBottom && bottom >= clientY) {
                    node.bgColor = node.style.backgroundColor;
                    node.style.backgroundColor = selectedTdBColor;
                    selectedCell.push(info);
                    if (bottom === downBottom) {
                      mergeColSpan += colSpan;
                    }
                    if (right === downRight) {
                      mergeRowSpan += rowSpan;
                    }
                    spanCount += rowSpan * colSpan;
                  }
                } else {
                  break;
                }
              }
            }
            if (hasNext) {
              break;
            }
          }
          selectedCellBack = selectedCell;
          mergeCellInfo = selectedCell[selectedCell.length - 1];
          mergeDiagonalCellInfo = selectedCell[0];
        }
        if (spanCount !== mergeColSpan * mergeRowSpan) {
          mergeButDisabled = true;
        }
      }
    } else {
      const cell = findTd(target);
      if (cell) {
        let className = cell.getAttribute('class');
        className = className.replace(' e-resize', '');
        className = className.replace(' n-resize', '');
        const { right, bottom } = cellInfos[cell.positionX][cell.positionY];
        if (right - clientX > 2 && right - clientX < 6) {
          className = className.concat(' e-resize');
          adjustSize = 1;
        } else if (bottom - clientY > 2 && bottom - clientY < 6) {
          className = className.concat(' n-resize');
          adjustSize = 2;
        } else {
          adjustSize = false;
        }
        cell.setAttribute('class', className);
      } else {
        adjustSize = false;
      }
    }
    event.stopPropagation();
    event.cancelBubble = true;
    return false;
  }

  // 鼠标抬起
  function onMouseUp(event) {
    mouseHasDown = false;
    adjustSize = false;
    if (cellHasChange) {
      cellHasChange = false;
      cellChange();
      pushHandle();
    }
  }

  /**
   * 根据组名自动查出这一组当中最后一行，并在最后一行添加新的组成员
   * @param {*} groupName 
   * @param {*} addCellInfos 
   * @param {*} value 给新增的单元格赋值 
   */
  function addCellsByGroupName(groupName, addCellInfos, value) {
    if (addCellInfos instanceof Array) {
      let infos;
      let info;
      let temp = 0;
      let indexJ = 0;
      let i = 0;
      let j = 0;
      let lastJ = 0;
      for (; i < cellInfos.length; i += 1) {
        infos = cellInfos[i];
        j = indexJ;
        while (j < infos.length) {
          info = infos[j];
          if (info && info.node.cellType.attrData.groupName == groupName) {
            if (temp != 1) {
              indexJ = j;
            }
            temp = 1;
            i += info.rowSpan - 1;
            break;
          } else if (temp == 1 && info) {
            temp = 2;
            break;
          }
          j += 1;
        }
        if (temp == 2) {
          i -= 1;
          break;
        }
      }
      infos = cellInfos[i];
      let baseCell;
      for (let i = 0; i < infos.length; i += 1) {
        baseCell = infos[i];
        if (baseCell) {
          break;
        }
      }
      const indexI = i + baseCell.rowSpan - 1;
      let item;
      const trs = [];
      let cols = 0;
      const rows = addCellInfos.length;
      const groupIndex = groupComponents[groupName].length;
      groupComponents[groupName].push([]);
      for (let i = 0; i < addCellInfos.length; i += 1) {
        infos = addCellInfos[i];
        const tr = gkhCreate('tr');
        for (let j = 0; j < infos.length; j += 1) {
          item = infos[j];
          if (i == 0) {
            cols += item[1];
          }
          tr.appendChild(createTd(item[4], setCellStyle(item), item[0], item[1], groupIndex, value));
        }
        trs.push(tr);
      }
      lastJ = indexJ + cols - 1;
      infos = cellInfos[indexI];
      if (!infos) return;
      for (let i = 0; i < infos.length; i += 1) {
        if (i < indexJ || i > lastJ) {
          info = infos[i];
          if (info) {
            info.node.rowSpan += rows;
            i += info.colSpan - 1;
          } else {
            for (let j = indexI - 1; j >= 0; j -= 1) {
              info = cellInfos[j][i];
              if (info && info.rowSpan > 1) {
                if (indexI < info.rowSpan + j) {
                  info.node.rowSpan += rows;
                  i += info.colSpan - 1;
                }
                break;
              }
            }
          }
        }
      }
      let pNode = baseCell.node.parentNode;
      let node = pNode.nextSibling;
      i = 1;
      while (i < baseCell.rowSpan) {
        if (node) {
          node = node.nextSibling;
          i += 1;
        } else {
          break;
        }
      }
      if (node instanceof Node) {
        for (let i = 0; i < trs.length; i += 1) {
          tbody.insertBefore(trs[i], node);
        }
      } else {
        for (let i = 0; i < trs.length; i += 1) {
          tbody.appendChild(trs[i]);
        }
      }
      cellChange();
    }
  }

  // 往后插入一行
  function insertAfterRow() {
    const { rowSpan, colSpan, positionX, positionY, parentNode } = mouseDownCell;
    let node = parentNode;
    const indexI = positionX + rowSpan - 1;
    const infos = cellInfos[indexI];
    let info;
    const newTr = gkhCreate('tr');
    let size = 0;
    for (let i = 0; i < infos.length; i += 1) {
      info = infos[i];
      if (info) {
        node = info.node.parentNode;
        if (info.rowSpan === 1) {
          size += info.colSpan;
        } else {
          info.node.rowSpan += 1;
        }
        i += info.colSpan - 1;
      } else {
        for (let j = indexI - 1; j >= 0; j -= 1) {
          info = cellInfos[j][i];
          if (info && info.rowSpan > 1) {
            if (indexI < info.rowSpan + j - 1) {
              info.node.rowSpan += 1;
              i += info.colSpan - 1;
            } else {
              size += info.colSpan;
            }
            break;
          }
        }
      }
    }
    while (size > 0) {
      newTr.appendChild(createTd());
      size -= 1;
    }
    if (node.nextSibling instanceof Node) {
      tbody.insertBefore(newTr, node.nextSibling);
    } else {
      tbody.appendChild(newTr);
    }
    cellChange();
    pushHandle();
  }

  const addBeforeRows = function (addCellInfos, node) { // 作废
    const cell = findTd(node);
    if (cell) {
      let infos;
      let item;
      const trs = [];
      let cols = 0;
      const rows = addCellInfos.length;
      for (let i = 0; i < addCellInfos.length; i += 1) {
        infos = addCellInfos[i];
        const tr = gkhCreate('tr');
        for (let j = 0; j < infos.length; j += 1) {
          item = infos[j];
          if (i == 0) {
            cols += item[1];
          }
          tr.appendChild(createTd(item[4], setCellStyle(item), item[0], item[1]));
        }
        trs.push(tr);
      }
      const { positionX, positionY, parentNode } = cell;
      const indexI = positionX - 1;
      infos = cellInfos[indexI];
      let info;
      let size = 0;
      cols += positionY;
      for (let i = 0; i < infos.length; i += 1) {
        if (i < positionY || i >= cols) {
          info = infos[i];
          if (info) {
            info.node.rowSpan += rows;
            i += info.colSpan - 1;
          } else {
            for (let j = indexI - 1; j >= 0; j -= 1) {
              info = cellInfos[j][i];
              if (info && info.rowSpan > 1) {
                if (indexI <= info.rowSpan + j - 1) {
                  info.node.rowSpan += rows;
                  i += info.colSpan - 1;
                }
                break;
              }
            }
          }
        }
      }
      for (let i = 0; i < trs.length; i += 1) {
        tbody.insertBefore(trs[i], parentNode);
      }
      cellChange();
    }
  };

  // 往前插入一行
  function insertBeforeRow() {
    const { positionX: indexI, parentNode } = mouseDownCell;
    const infos = cellInfos[indexI];
    let info;
    const newTr = gkhCreate('tr');
    let size = 0;
    for (let i = 0; i < infos.length; i += 1) {
      info = infos[i];
      if (info) {
        node = info.node.parentNode;
        size += info.colSpan;
        i += info.colSpan - 1;
      } else {
        for (let j = indexI - 1; j >= 0; j -= 1) {
          info = cellInfos[j][i];
          if (info && info.rowSpan > 1) {
            if (indexI <= info.rowSpan + j - 1) {
              info.node.rowSpan += 1;
              i += info.colSpan - 1;
            } else {
              size += info.colSpan;
            }
            break;
          }
        }
      }
    }
    while (size > 0) {
      newTr.appendChild(createTd());
      size -= 1;
    }
    tbody.insertBefore(newTr, parentNode);
    cellChange();
    pushHandle();
  }

  function delRow() {
    const { positionX, parentNode } = mouseDownCell;
    const infos = cellInfos[positionX];
    const nextInfos = cellInfos[positionX + 1];
    let info;
    let hasNext = true;
    for (let i = 0; i < infos.length; i += 1) {
      info = infos[i];
      if (info) {
        const { rowSpan, colSpan } = info;
        i = i + colSpan - 1;
        if (rowSpan > 1) {
          hasNext = true;
          for (let k = i + 1; k < nextInfos.length; k += 1) {
            info = nextInfos[k];
            if (info) {
              hasNext = false;
              info.node.parentNode.insertBefore(
                createTd({}, undefined, rowSpan - 1, colSpan),
                info.node,
              );
              break;
            }
          }
          if (hasNext) {
            for (let k = i - 1; k >= 0; k -= 1) {
              info = nextInfos[k];
              if (info) {
                info.node.parentNode.appendChild(createTd({}, undefined, rowSpan - 1, colSpan));
                break;
              }
            }
          }
        }
      } else {
        for (let j = positionX - 1; j >= 0; j -= 1) {
          info = cellInfos[j][i];
          if (info && info.rowSpan > 1) {
            info.node.rowSpan -= 1;
            i += info.colSpan - 1;
            break;
          }
        }
      }
    }
    tbody.removeChild(parentNode);
    cellChange();
    pushHandle();
  }

  function addCol(hasAfter) {
    const { positionX, positionY, colSpan } = mouseDownCell;
    const indexJ = hasAfter ? positionY + colSpan : positionY;
    let infos;
    let info;
    let hasNext;
    for (let i = 0; i < cellInfos.length; i += 1) {
      infos = cellInfos[i];
      info = infos[indexJ];
      if (info) {
        const { rowSpan, colSpan, node } = info;
        if (rowSpan > 1) {
          for (let k = 1; k < rowSpan; k += 1) {
            infos = cellInfos[k + i];
            hasNext = true;
            for (let m = indexJ + 1; m < infos.length; m += 1) {
              info = infos[m];
              if (info) {
                info.node.parentNode.insertBefore(createTd(), info.node);
                hasNext = false;
                break;
              }
            }
            if (hasNext) {
              for (let m = indexJ - 1; m >= 0; m -= 1) {
                info = infos[m];
                if (info) {
                  info.node.parentNode.appendChild(createTd());
                  break;
                }
              }
            }
          }
        }
        node.parentNode.insertBefore(createTd(), node);
      } else {
        for (let k = indexJ - 1; k >= 0; k -= 1) {
          info = infos[k];
          if (info && info.colSpan > 1) {
            info.node.colSpan += 1;
            i += info.rowSpan - 1;
            break;
          }
        }
      }
    }
    cellChange();
    pushHandle();
  }

  function addColAfter() {
    addCol(true);
  }

  function addColBefore() {
    addCol(false);
  }
  /**
   * 通过组名获取组成员
   * @param {*} groupName 
   * @returns 
   */
  function findCellsByGroupName(groupName) {
    const cells = [];
    let infos;
    let info;
    let temp = 0;
    let hasExist = false;
    let arrs = [];
    let indexJ = 0;
    let j = 0;
    for (let i = 0; i < cellInfos.length; i += 1) {
      infos = cellInfos[i];
      temp = 0;
      if (hasExist) {
        arrs = [];
      }
      j = indexJ;
      while (j < infos.length) {
        info = infos[j];
        if (info && info.node.cellType.attrData.groupName == groupName) {
          if (!hasExist) {
            indexJ = j;
          }
          arrs.push(info);
          temp = 1;
          hasExist = true;
        } else if (temp) {
          break;
        }
        j += 1;
      }
      if (arrs.length > 0) {
        cells.push(arrs);
      }
      if (hasExist && temp == 0) {
        break;
      }
    }
    return cells;
  }
  /**
   * 通过组名删除组成员
   * @param {*} groupName 
   * @param {*} rows 
   */
  function delCellsByGroupName(groupName, rows) {
    groupComponents[groupName].pop();
    const cells = findCellsByGroupName(groupName);
    let infos = cells[0];
    const indexJ = infos[0].node.positionY;
    const lastJ = infos[infos.length - 1].node.positionY;
    infos = cells[rows - 1];
    let info = infos[0];
    const indexI = info.node.positionX;
    infos = cellInfos[indexI];
    for (let i = 0; i < infos.length; i += 1) {
      if (i < indexJ || i > lastJ) {
        info = infos[i];
        if (info) {
          info.node.rowSpan -= rows;
          i += info.colSpan - 1;
        } else {
          for (let j = indexI - 1; j >= 0; j -= 1) {
            info = cellInfos[j][i];
            if (info && info.rowSpan > 1) {
              if (indexI < info.rowSpan + j) {
                info.node.rowSpan -= rows;
                i += info.colSpan - 1;
              }
              break;
            }
          }
        }
      }
    }
    let node;
    for (let i = cells.length - rows; i < cells.length; i += 1) {
      node = cells[i][0].node;
      if (node) {
        node.parentNode.parentNode.removeChild(node.parentNode);
      }
    }
    cellChange();
  }

  function delCol() {
    const { positionX, positionY } = mouseDownCell;
    let info;
    let infos;
    let hasNext;
    for (let i = 0; i < cellInfos.length; i += 1) {
      infos = cellInfos[i];
      info = infos[positionY];
      if (info) {
        const { rowSpan, colSpan, node } = info;
        i += rowSpan - 1;
        if (colSpan > 1) {
          hasNext = true;
          for (let j = positionY + 1; j < infos.length; j += 1) {
            info = infos[j];
            if (info) {
              info.node.parentNode.insertBefore(
                createTd({}, undefined, rowSpan, colSpan - 1),
                info.node,
              );
              hasNext = false;
              break;
            }
          }
          if (hasNext) {
            for (let k = positionY - 1; k >= 0; k -= 1) {
              info = infos[k];
              if (info) {
                info.node.parentNode.appendChild(createTd({}, undefined, rowSpan, colSpan - 1));
              }
            }
          }
        }
        node.parentNode.removeChild(node);
      } else {
        for (let j = positionY - 1; j >= 0; j -= 1) {
          info = infos[j];
          if (info && info.colSpan > 1) {
            info.node.colSpan -= 1;
            i += info.node.rowSpan - 1;
          }
        }
      }
    }
    cellChange();
    pushHandle();
  }

  function mergeCell() {
    if (selectedCell.length > 1) {
      mergeCellInfo.node.rowSpan = tableCols === mergeColSpan ? 1 : mergeRowSpan;
      mergeCellInfo.node.colSpan = tableRows === mergeRowSpan ? 1 : mergeColSpan;
      mergeCellInfo.node.style.backgroundColor = mergeCellInfo.node.bgColor;
      for (let i = 0; i < selectedCell.length; i += 1) {
        const preCellEl = selectedCell[i];
        if (mergeCellInfo !== preCellEl) {
          preCellEl.node.parentNode.removeChild(preCellEl.node);
        }
      }
      cellChange();
      pushHandle();
    }
  }

  // 按行拆分单元格
  function splitCellByRow() {
    const { positionX, positionY, rowSpan, colSpan, cellType, offsetHeight } = mouseDownCell;
    let info;
    let hasNext = true;
    const height = (offsetHeight / 2).toString().concat('px');
    if (rowSpan > 1) {
      const newRowSpan = rowSpan / 2;
      const tdNode = createTd(cellType.attrData, { height }, newRowSpan, colSpan);
      mouseDownCell.rowSpan = newRowSpan;
      const infos = cellInfos[positionX + newRowSpan];
      for (let i = positionY; i < infos.length; i += 1) {
        info = infos[i];
        if (info) {
          info.node.parentNode.insertBefore(tdNode, info.node);
          hasNext = false;
          break;
        }
      }
      if (hasNext) {
        for (let i = 0; i < infos.length; i += 1) {
          info = infos[i];
          if (info) {
            info.node.parentNode.appendChild(tdNode);
            break;
          }
        }
      }
    } else {
      const infos = cellInfos[positionX];
      for (let i = 0; i < infos.length; i += 1) {
        if (i === positionY) {
          continue;
        }
        info = infos[i];
        if (info) {
          info.node.rowSpan += 1;
          i += info.colSpan - 1;
        } else {
          for (let j = positionX - 1; j >= 0; j -= 1) {
            info = cellInfos[j][i];
            if (info && info.rowSpan > 1) {
              info.node.rowSpan += 1;
              i += info.colSpan - 1;
              break;
            }
          }
        }
      }
      const tr = mouseDownCell.parentNode.nextSibling;
      if (tr instanceof Node) {
        tbody.insertBefore(
          gkhCreate('tr', {
            child: createTd(cellType.attrData, { height }, 1, colSpan),
          }),
          tr,
        );
      } else {
        tbody.appendChild(
          gkhCreate('tr', {
            child: createTd(cellType.attrData, { height }, 1, colSpan),
          }),
        );
      }
    }
    mouseDownCell.style.height = height;
    cellChange();
    pushHandle();
  }

  function splitCellByCol() {
    const {
      positionX,
      positionY,
      rowSpan,
      colSpan,
      cellType,
      parentNode,
      nextSibling,
      offsetWidth
    } = mouseDownCell;
    let info;
    let hasNext = true;
    let newColSpan = colSpan / 2;
    const width = (offsetWidth / 2).toString().concat('px');
    const max = positionX + rowSpan;
    if (colSpan < 2) {
      newColSpan = 1;
      for (let i = 0; i < cellInfos.length; i += 1) {
        if (i < positionX || i >= max) {
          info = cellInfos[i][positionY];
          if (info) {
            info.node.colSpan += 1;
            i += info.rowSpan - 1;
          } else {
            for (let j = positionY - 1; j >= 0; j -= 1) {
              info = cellInfos[i][j];
              if (info) {
                info.node.colSpan += 1;
                i += info.rowSpan - 1;
                break;
              }
            }
          }
        }
      }
    }
    mouseDownCell.colSpan = newColSpan;
    mouseDownCell.style.width = width;
    if (nextSibling instanceof Node) {
      parentNode.insertBefore(
        createTd(cellType.attrData, { width }, rowSpan, newColSpan),
        nextSibling,
      );
    } else {
      parentNode.appendChild(createTd(cellType.attrData, { width }, rowSpan, newColSpan));
    }
    cellChange();
    pushHandle();
  }

  this.renderTemplate = function (templateData) {
    renderTableTemplate(templateData);
    pushHandle();
  };
  this.getTemplateData = tableTemplateData;
  /**
   * 改变单元格高度
   * @param {*} targetNode 单元格子节点或单元格本身
   * @param {*} changeSize 变化的大小  原高度100 变化后的高度120  则这个值为120-100=20
   * @param {*} height 直接设定单元格高度 当changeSize传入值时这个值无效
   */
  this.cellHeightChange = function (targetNode, changeSize, height) {
    if (targetNode instanceof Node) {
      if (changeSize || height > 8) {
        const cell = findTd(targetNode);
        if (cell) {
          const { positionX, rowSpan, positionY } = cell;
          const infos = cellInfos[positionX + rowSpan - 1];
          let info;
          const adjustCellInfos = [];
          let minHeight = 1000000;
          for (let i = 0; i < infos.length; i += 1) {
            info = infos[i];
            if (info) {
              adjustCellInfos.push({
                height: info.height,
                node: info.node,
              });
              i += info.colSpan - 1;
              if (minHeight > info.height) {
                minHeight = info.height;
              }
            } else {
              for (let j = positionX - 1; j >= 0; j -= 1) {
                info = cellInfos[j][i];
                if (info && info.rowSpan > 1) {
                  adjustCellInfos.push({
                    height: info.height,
                    node: info.node,
                  });
                  i += info.colSpan - 1;
                  break;
                }
              }
            }
          }
          if (changeSize) {
            adjustCellInfos.forEach(({ height, node }) => {
              if (node !== targetNode) {
                node.style.height = (height + changeSize).toString().concat('px');
              }
            });
            cellChange();
          } else if (height > 20) {
            changeSize = height - minHeight;
            adjustCellInfos.forEach(({ height, node }) => {
              node.style.height = (height + changeSize).toString().concat('px');
            });
            cellChange();
          }
        }
      }
    }
  }

  /**
   * 设置单元格样式
   * @param {*} style 
   */
  this.setCellStyle = function (style) {
    if (style instanceof Object) {
      if (selectedCell.length > 0) {
        let node;
        for (let i = 0; i < selectedCell.length; i += 1) {
          node = selectedCell[i].node;
          if (style.backgroundColor) {
            node.bgColor = style.backgroundColor;
          }
          for (var key in style) {
            node.style[key] = style[key];
          }
        }
      } else if (mouseDownCell) {
        for (var key in style) {
          mouseDownCell.style[key] = style[key];
        }
      }
      cellChange(false);
    }
  }

  /**
   * 设置表格边框颜色
   * @param {*} color 
   */
  this.setTableBorderColor = function (color) {
    tableContainer.style.borderColor = color;
  }

  this.sizeChange = cellChange;

  this.tableBorder = function (arg) {
    tableContainer.border = arg ? 1 : 0;
  }

  this.getValues = function () {
    let infos;
    let info;
    let groups = new Map();
    const values = {};
    for (let i = 0; i < cellInfos.length; i += 1) {
      infos = cellInfos[i];
      const temp = new Map();
      for (let j = 0; j < infos.length; j += 1) {
        info = infos[j];
        if (info) {
          const { cellType, cellType: { attrData: { groupName, fieldName }, type } } = info.node;
          if (type != 5) {
            if (groupName) {
              if (!temp.get(groupName)) {
                temp.set(groupName, []);
              }
              temp.get(groupName).push(cellType)
            } else if (fieldName && cellType.getValue) {
              values[fieldName] = cellType.getValue();
            }
          }
        }
      }
      if (temp.size > 0) {
        temp.forEach((value, key) => {
          let arrs = groups.get(key);
          if (!arrs) {
            arrs = [];
            groups.set(key, arrs);
          }
          arrs.push(value);
        })
      }
    }
    let rows;
    groups.forEach((value, key) => {
      const but = addButtons.find((item) => item.attrData.fieldName == key);
      if (but) {
        rows = but.attrData.rows;
        const arrValue = [];
        let temp;
        value.forEach((item, index) => {
          if (index % rows == 0) {
            temp = {};
            arrValue.push(temp);
          }
          item.forEach(cell => {
            if (cell.attrData.fieldName && cell.getValue) {
              temp[cell.attrData.fieldName] = cell.getValue();
            }
          })
        });
        values[key] = arrValue;
      } else {
        console.warn("组名为：".concat(key).concat("的新增按钮信息没找到，获取的组的值会缺失！"));
      }
    })
    return values;
  }
  this.setValues = function (arg) {
    if (arg instanceof Object) {
      var obj;
      for (let key in arg) {
        obj = valueHandle[key];
        if (obj) {
          obj.setValue(arg[key]);
        } else {
          console.warn("字段[".concat(key).concat("]对应表格中没有相对于的setValue方法，无法赋值！"));
        }
      }
    } else {
      console.warn("传入数据格式不对，需要Object类型。");
    }
  }
  if (mode == 1) {
    tableContainer.addEventListener('mousemove', onMouseMove, false);
    tableContainer.addEventListener('mousedown', onMouseDown, false);
    tableContainer.addEventListener('mouseup', onMouseUp, false);
  }
  /**
   * 获取传入单元格，获取重新渲染所需数据
   * @param {*} groupCells 单元格，数组，通过getSelectedCell获取
   * @param {*} groupName 组名
   * @returns 
   */
  this.getGroupCellsInfo = function (groupCells, groupName) {
    tableWidth = tbody.offsetWidth;
    const infos = [];
    if (groupCells.length > 0) {
      let top = 0;
      let info;
      let cellInfo = [];
      for (let i = 0; i < groupCells.length; i += 1) {
        info = groupCells[i];
        info.node.cellType.attrData.groupName = groupName;
        if (top != info.top) {
          top = info.top;
          cellInfo = [];
          infos.push(cellInfo);
        }
        cellInfo.push(getCellData(info));
      }
    }
    let arrs = [];
    let cols = 0;
    let info;
    for (let i = 0; i < infos.length; i += 1) {
      arrs = infos[i];
      for (let j = 0; j < arrs.length; j += 1) {
        info = arrs[j];
        if (i == 0) {
          cols += info[1];
        } else if (info[1] == cols) {
          info[0] = 1;
        }
      }
    }
    return infos;
  }
  /**
   * 给选中的单元设为一个组
   * @param {*} groupName 组名，表格当中必须唯一
   * @returns 
   */
  this.setGroupOnSelected = function (groupName) { // 作废
    tableWidth = tbody.offsetWidth;
    const infos = [];
    if (selectedCellBack.length > 0) {
      let top = 0;
      let info;
      let cellInfo = [];
      for (let i = 0; i < selectedCellBack.length; i += 1) {
        info = selectedCellBack[i];
        info.node.cellType.attrData.groupName = groupName;
        if (top != info.top) {
          top = info.top;
          cellInfo = [];
          infos.push(cellInfo);
        }
        cellInfo.push(getCellData(info));
      }
    }
    let arrs = [];
    let cols = 0;
    let info;
    for (let i = 0; i < infos.length; i += 1) {
      arrs = infos[i];
      for (let j = 0; j < arrs.length; j += 1) {
        info = arrs[j];
        if (i == 0) {
          cols += info[1];
        } else if (info[1] == cols) {
          info[0] = 1;
        }
      }
    }
    return {
      selectedCell: selectedCellBack,
      infos,
      rows: infos.length
    };
  }
  /**
   * 高亮组成员单元格 
   * @param {*} groupCells 数组，通过getSelectedCells获取的数据
   */
  this.showGroupCells = function (groupCells) {
    if (groupCells) {
      clearSelected();
      selectedCell = groupCells;
      selectedCell.forEach(({ node }) => {
        node.bgColor = node.style.backgroundColor;
        node.style.backgroundColor = selectedTdBColor;
      });
    }
  }
  this.getSelectedCells = function () {
    return selectedCellBack;
  }
  this.addCellsByGroupName = addCellsByGroupName;
  this.delCellsByGroupName = delCellsByGroupName;
  this.getGroupComponents = function (groupName) {
    return groupComponents[groupName];
  }
  this.findGroupCells = function (groupName) {
    const cells = findCellsByGroupName(groupName);
    let temp = [];
    cells.forEach(item => {
      temp = temp.concat(item);
    })
    return temp;
  }
  return this;
};

export default GkhTableTemplate;
